ci: fold the imported workflows into this repo's set - #4256
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 2c34df3. Configure here.
090eac9 to
aabc99c
Compare
740238c to
1f3f148
Compare
825db3b to
cd063da
Compare
71accae to
59a56a9
Compare
00d7caf to
56cb7a0
Compare
59a56a9 to
3ee3803
Compare
3ee3803 to
083de2f
Compare
There was a problem hiding this comment.
🟡 Changes recommended
The new solana.yml installs the wrong Rust toolchain (and misses required components for lint), which can break make lint and produce inconsistent CI results for the solana/ workspace.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR completes step 5 of the monorepo migration by moving imported GitHub Actions workflows into the repository-root .github/workflows/ set, rewriting paths for the merged workspace layout, and deleting the unused imported .github directories.
Changes:
- Add new root workflows for
solana/CI,offchain/fork-based local-validator tests, and the Elixir scheduler CI. - Port and retarget the five offchain release workflows to run GoReleaser from the repository root with updated config paths and release destination.
- Update the root changelog reminder to include per-offchain-subproject changelog requirements, and remove legacy offchain/solana workflow files that never executed in this repo.
File summaries
| File | Description |
|---|---|
solana/.github/workflows/verify-build.yml |
Deleted imported workflow that never ran from a nested .github/ directory. |
solana/.github/workflows/rust.yml |
Deleted imported workflow that never ran from a nested .github/ directory. |
solana/.github/workflows/local-validator.yml |
Deleted imported workflow that never ran from a nested .github/ directory. |
offchain/.github/workflows/local-validator.yml |
Deleted imported workflow that never ran from a nested .github/ directory. |
offchain/.github/workflows/ci.yml |
Deleted imported offchain CI workflow; coverage-floor job is intentionally not carried over. |
offchain/.github/workflows/changelog-reminder.yml |
Deleted imported workflow; logic is merged into root changelog-reminder.yml. |
offchain/.github/pull_request_template.md |
Deleted imported PR template from nested .github/. |
offchain/scripts/release-rc.sh |
Adjusted paths and repo-root resolution for RC releases in the merged workspace. |
offchain/release/.goreleaser.sentinel.yaml |
Updated packaging paths and release destination repo name. |
offchain/release/.goreleaser.doublezero-solana-validator-debt.yaml |
Updated packaging paths and release destination repo name. |
offchain/release/.goreleaser.doublezero-solana-cli.yaml |
Updated release destination repo name. |
offchain/release/.goreleaser.doublezero-offchain-scheduler.yaml |
Updated Elixir build directories, prebuilt paths, and release destination repo name. |
offchain/release/.goreleaser.contributor-rewards.yaml |
Updated packaging paths and release destination repo name. |
offchain/Justfile |
Removed offchain-local Rust recipes and kept scheduler-focused Elixir and fork-test recipes. |
CHANGELOG.md |
Documented the workflow consolidation and the migration-related CI changes. |
.github/workflows/solana.yml |
Added root CI workflow for the nested solana/ workspace, including SBF and checksum gates. |
.github/workflows/offchain.local-validator.yml |
Added root workflow for the two live offchain fork tests, running from repo root. |
.github/workflows/elixir.yml |
Added root workflow for scheduler Elixir checks on PRs that touch offchain/scheduler/. |
.github/workflows/changelog-reminder.yml |
Extended reminder to require offchain subproject changelogs when those subtrees change. |
.github/workflows/rust.yml |
Expanded rust-cli-static to validate static musl linkage for all released CLIs. |
.github/workflows/release.contributor-rewards.yml |
Retargeted release job to root-run GoReleaser config under offchain/release/ and pinned toolchain. |
.github/workflows/release.doublezero-solana-cli.yml |
Retargeted release job to root-run GoReleaser config under offchain/release/ and pinned toolchain. |
.github/workflows/release.offchain-sentinel.yml |
Renamed workflow and retargeted GoReleaser config under offchain/release/ with pinned toolchain. |
.github/workflows/release.solana-validator-debt.yml |
Retargeted release job to root-run GoReleaser config under offchain/release/ and pinned toolchain. |
.github/workflows/release.offchain-scheduler.yml |
Retargeted scheduler release to root-run GoReleaser config, updated caches/paths, and pinned Rust toolchain for NIF build. |
Review details
Suppressed comments (3)
.github/workflows/solana.yml:38
- Issue
The test job installs the wrong Rust toolchain for the solana workspace.
Context
The solana workspace pins Rust 1.91 in solana/rust-toolchain.toml, but this job installs the default stable toolchain instead.
Proposed Fix
Install Rust 1.91 in this job.
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
.github/workflows/solana.yml:48
- Issue
The doc job installs the wrong Rust toolchain for the solana workspace.
Context
The solana workspace pins Rust 1.91 in solana/rust-toolchain.toml, but this job installs the default stable toolchain instead.
Proposed Fix
Install Rust 1.91 in this job.
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
.github/workflows/solana.yml:61
- Issue
The SBF test job installs the wrong Rust toolchain for the solana workspace.
Context
The solana workspace pins Rust 1.91 in solana/rust-toolchain.toml, but this job installs the default stable toolchain instead.
Proposed Fix
Install Rust 1.91 in this job.
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- Files reviewed: 25/25 changed files
- Comments generated: 4
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Step 5 of the monorepo migration. The 11 workflows that came with doublezero-offchain and doublezero-solana are folded in and the imported `.github` directories are deleted. GitHub reads workflows only at the repository root, so nothing in those directories ever ran here. Five release workflows come across, one per component, matching the shape this repo already uses. They run goreleaser from the repository root rather than from `offchain/`: the merged workspace writes to the root `target/`, which is where goreleaser's rust builder looks for the binary it packages. The five goreleaser configs get their relative paths rewritten to match, and `release.github.name` moves from `doublezero-offchain` to `doublezero` so the releases land here. This repo already holds the three secrets they need. Two workflows are new rather than ported. `solana` runs that tree's own lint, library tests, docs and SBF tests plus the checksum gate, because the tree is excluded from the root workspace and `rust.yml` never reaches it, so it would otherwise have no CI here at all. `elixir` runs the scheduler's format check, compile, credo and tests on the pull request that changes it; upstream those ran on a release tag alone, so a pull request that broke the scheduler passed. Offchain's `ci.yml` is dropped, since `make rust-build`, `make rust-lint` and `make rust-test` now cover those crates. Two things it carried are kept elsewhere: `rust-cli-static` grows from the client alone to all five released CLIs, and the per-crate changelog check moves into this repo's `changelog-reminder`. One thing is not kept: the `just ci` coverage floor, whose workspace no longer exists. `offchain/Justfile` keeps its Elixir recipes and loses its Rust ones, which would otherwise run cargo over the whole workspace with a different fmt and clippy line than CI uses. `offchain/scripts/release-rc.sh` resolves the repository root two levels up, so local release candidates build against the merged workspace.
goreleaser runs from the repository root now, and the four mix hooks and the package contents were repointed, but the prebuilt builder's own path was not. It uses a different key and a ./ prefix, so it slipped through the rewrite. A tagged scheduler release would have run the hooks, built the release into offchain/scheduler/_build, then failed to find the binary. Audited every path-like value across the five configs. This was the only one left. The remaining relative path, /opt/doublezero-offchain-scheduler/bin/scheduler, is where the package installs on the target machine, not a build path.
The ported workflow ran `cargo build --bin doublezero-solana` from the
repository root, which fails here:
error: manifest path `/home/runner/work/doublezero/doublezero` contains no
package: The manifest is virtual, and the workspace has no members.
The root workspace sets `default-members = []`, so a bare cargo command
selects nothing. doublezero-offchain's workspace had no such restriction, so
these commands worked there unchanged.
Each call now names its package. Checked locally: all four binaries build and
land in target/debug at the repository root, which is where the fork scripts
look for them.
The three workflows added here filtered by path on pull_request but not on push, so every push to main or a hotfix branch started them whether or not it touched their trees. That is two mainnet-beta fork jobs, six solana jobs including two Docker artifact builds, and the Elixir suite, on pushes that cannot affect any of them. Each push trigger now carries the same paths list as its pull_request trigger.
…orkflow The solana jobs used dtolnay/rust-toolchain@stable, so the toolchain came from whatever rustup resolved at the time rather than from solana/rust-toolchain.toml, which pins 1.91 with rustfmt and clippy. The root rust-toolchain.toml does not apply to that tree, and naming a version in the workflow as well would give two places to drift. Each job now runs `rustup toolchain install` with no arguments, from solana/, which installs exactly what that tree's toolchain file names, components included. This is how both imported repositories set their toolchain up.
ed84a27 to
a2b7d84
Compare
**Stacked on #4256**, top of the migration stack, so the diff shown here is the sync alone. #4240 captured `doublezero-offchain` at its #414. Three pull requests landed there afterwards, so the imported tree went in three commits stale. This replays them. ## Summary - **offchain#415** removes `doublezero-solana shreds pay`. `withdraw`, `list`, `payments` and `price` stay. This is the other half of #4248 in this repo, which removed the QA e2e that funded a seat through it. - **offchain#416** removes the fund-seat instruction from the offchain Solana SDK, while `shreds payments` keeps reading leftover fund-seat transactions so history stays legible. - **offchain#417** moves the solana-cli crate to 0.5.12. - Each commit keeps its original author, date and message. The bare `(#N)` references are rewritten to name `malbeclabs/doublezero-offchain`, exactly as the import rewrote its own 451, so a reader following a link does not land on an unrelated pull request in this repo. - `offchain/Cargo.lock` is left out of the replay, because #4255 deleted it. The version bump it carried lands in the root lockfile instead, which is where the crate resolves now. - **`solana/` needs no sync.** Its upstream tip is the tip that was imported. ## Testing Verification - `git diff` between `offchain/crates` here and the same tree at upstream `main` comes back to exactly the files steps 3, 4 and 5 changed, and nothing else: the manifests, the clippy fixes, and step 3's `feed_pks` compatibility change. Nothing upstream is missing and nothing extra crept in. - `cargo clippy -p doublezero-solana-cli -p doublezero-solana-sdk --all-targets` with this repo's lint line: clean. - `cargo test` for both crates: 161 passed. - Nothing outside `offchain/` referenced the removed command. The only match in the repo is a CHANGELOG line describing #4248, which is a historical note. ## Note for whoever reads the per-crate changelogs The changelog text these commits add still carries bare `(#N)` references, because the import rewrote commit messages only and left file contents alone. Every imported per-crate changelog is like this. Rewriting them is a separate job, if it is worth doing at all. --------- Co-authored-by: Martin Sander <69667393+martinsander00@users.noreply.github.com>

Step 5 of the monorepo migration, per
docs/superpowers/specs/2026-08-27-monorepo-migration-design.md. Stacked on #4255 and based on that branch, so the diff shown here is step 5 alone.The 11 workflows that came with the two source repos are folded into this repo's set, and the imported
.githubdirectories are deleted. GitHub reads workflows only at the repository root, so nothing in those directories has ever run here.Where each imported workflow went
release.contributor-rewards.ymlrelease.contributor-rewards.ymlrelease.doublezero-solana-cli.ymlrelease.doublezero-solana-cli.ymlrelease.sentinel.ymlrelease.offchain-sentinel.ymlrelease.solana-validator-debt.ymlrelease.solana-validator-debt.ymlrelease.scheduler.ymlrelease.offchain-scheduler.ymllocal-validator.ymloffchain.local-validator.yml, two live jobs of fourci.ymlmake rust-build/rust-lint/rust-testcover those crates nowchangelog-reminder.ymlchangelog-reminder.ymlrust.yml+verify-build.ymlsolana.ymllocal-validator.ymlif: falseupstreamelixir.yml, which had no upstream equivalent in CISummary
offchain/. The merged workspace writes to the roottarget/, which is where goreleaser's rust builder looks for the binary it packages; running it fromoffchain/would send it looking inoffchain/target/. Every relative path inside the five configs is rewritten to match, including the scheduler's fourmixhooks and its_buildsource.release.github.namemoves fromdoublezero-offchaintodoublezeroin all five configs, so the releases land on this repository. Theownerwas already corrected during the org move. This repo already holdsCLOUDSMITH_TOKEN,GORELEASER_KEYandSLACK_BOTS_WEBHOOK, so the spec's "copy three secrets" step is already done.solanaworkflow, and it matters more than a port. Thesolana/tree is an excluded nested workspace, sorust.ymlnever reaches it: without this, the two Solana L1 programs would sit in this repo with no CI at all. It runs that tree's own lint, library tests, docs and SBF tests for both networks, plus the checksum gate that rebuilds the artifacts and verifies them againstsolana/programs/sha256sums_*.txt. Path-scoped tosolana/**.elixirworkflow, path-scoped tooffchain/scheduler/**: format check, compile with warnings as errors, credo, tests. Upstream these ran on a release tag only, so a pull request that broke the scheduler passed and the tag failed later.offchain-local-validatorruns from the repository root, because the fork scripts resolve their binaries astarget/debug/<name>and create their keypairs andtest-ledger/in the working directory, so all of it has to agree on one. Path-scoped tooffchain/**,solana/**and the root manifests rather than running on every pull request as it did in a quieter repo.rust-cli-staticcovers all five released CLIs instead of the client alone, which is what offchain'srust-musl-staticjob did for its four. Each package is built on its own so feature unification matches the release. The job keeps its name, since it is a required status check.changelog-reminderkeeps offchain's per-crate check, paths moved underoffchain/. This is a union, not a dedupe: a change to one of those 13 subprojects now needs both the rootCHANGELOG.mdand that subproject's own.What is deliberately not carried over
just cicoverage floor (cargo llvm-cov nextest --fail-under-lines 25). It measured a workspace that no longer exists, and running it over the merged workspace would both mean something different and cost a full instrumented build of 37 crates on every run.if: false, one commented out with a note about bringing it back. Both are in the imported history if wanted.offchain/Justfile's Rust recipes. Fromoffchain/they would now run cargo over the whole workspace, and with a different fmt line (group_imports=StdExternalCrate) and clippy line than CI uses. The Elixir recipes stay, plus two fork-test recipes that cd to the root.Testing Verification
actionlintover every new and changed workflow: no errors. The only output is SC2086 info notes on$SOLANA_CLIand$GITHUB_PATH, the same pattern the existingrust.ymljobs already carry.changelog-remindercheck parses underbash -n, andoffchain/scripts/release-rc.shstill parses after the path changes.just -linoffchain/lists the trimmed recipe set.cd solana && make lintpasses, which is the jobsolana.ymlruns first. Worth stating because step 4 reformatted three files in that tree with the root'simports_granularity=Crate: plain rustfmt preserves existing import grouping, so solana's owncargo fmt --checkstill agrees.NETWORKis passed asmainnet-betaordevelopmentexplicitly, never empty:solana/Makefilevalidates it and errors on anything else.